import datetime
from datetime import timedelta
import datetime
import requests
import json
import pandas as pd
import time
from basic_params import Basic_var, main_start_Que
from queue import Queue
from apscheduler.schedulers.background import BackgroundScheduler


def get_timedelta_second(t_start, t_end):
    '''
    计算交易持续时间以及休市时间长度
    第二天凌晨夜盘改变计算方法
    '''
    today = datetime.datetime.today()
    dt_start = (datetime.datetime.combine(today, t_start))
    if t_end.hour > 3:
        dt_end = (datetime.datetime.combine(today, t_end))
    else:
        dt_end = (datetime.datetime.combine(today + timedelta(days=1), t_end))
    return (dt_end - dt_start).total_seconds()


def time_flag_config():
    '''# 反复设置time_flag并按固定时间差执行暂停 time_flag为false时行情不会放入queue
    # 08:58:55打开
    # 11:30:05关闭
    # 13:28:55打开
    # 15:00:05关闭
    # 20:58:55打开
    # 02:30:05关闭'''
    t_start_8 = datetime.time(8, 58, 55)
    t_end_11 = datetime.time(11, 30, 5)
    t_start_13 = datetime.time(13, 28, 55)
    t_end_15 = datetime.time(15, 00, 5)
    t_start_20 = datetime.time(20, 58, 55)
    t_end_2 = datetime.time(2, 30, 5)

    Basic_var.time_flag = True
    # 按早盘持续时间暂停 保证time_flag为True
    time.sleep(get_timedelta_second(t_start_8, t_end_11))
    Basic_var.time_flag = False
    # 按早-午盘时间差执行暂停 保证time_flag为True
    time.sleep(get_timedelta_second(t_end_11, t_start_13))
    Basic_var.time_flag = True
    # 按午盘持续时间暂停 保证time_flag为True
    time.sleep(get_timedelta_second(t_start_13, t_end_15))
    Basic_var.time_flag = False
    # 按午-夜盘时间差执行暂停 保证time_flag为True
    time.sleep(get_timedelta_second(t_end_15, t_start_20))
    Basic_var.time_flag = True
    # 按夜盘时间差执行暂停 保证time_flag为True
    time.sleep(get_timedelta_second(t_start_20, t_end_2))
    Basic_var.time_flag = False


def time_unsub(future_l):
    '''
    夜盘中，取消订阅所有已停止交易品种
    sub_id 
    '''
    sub_id = [x.split('.')[1]
              for x in Basic_var.excg_instrID_list]  # 去除出exg_instrID_listd中交易所信息后的全部已订阅id
    unsub_id = list(filter(lambda x: ''.join(
        filter(str.isalpha, x)) in future_l, sub_id))  # 获取全部已停止交易的unsub_id
    split = [unsub_id[i:i+50]
             for i in range(0, len(unsub_id), 50)]  # 将全部unsub_id分段为元素长度50的list
    for id in split:
        Basic_var.mduserapi.UnSubscribeMarketData(
            [i.encode('utf-8') for i in id], len(id))


def create_timeflag_unsub_sche():
    '''
    增加一个sche控制异常行情过滤标识以及取消夜盘23点、1点品种订阅(取消订阅为了防止遇到异常行情/提前设置好sche参数
    '''
    scheduler = BackgroundScheduler()
    today = datetime.datetime.today()
    start_time = datetime.time(hour=8, minute=58, second=30)

    unsub_time_23 = datetime.time(hour=23, minute=00, second=15)
    unsub_time_01 = datetime.time(hour=1, minute=00, second=15)

    start_date = datetime.datetime.combine(today, start_time)
    unsub_date_23 = datetime.datetime.combine(today, unsub_time_23)
    unsub_date_01 = datetime.datetime.combine(
        today + timedelta(days=1), unsub_time_01)

    # 在start_time8:58:30开始time_flag_config()
    scheduler.add_job(time_flag_config, 'date',
                      run_date=start_date, misfire_grace_time=5)
    # 在unsub_time_23 23:00:15开始time_unsub
    scheduler.add_job(time_unsub, 'date', run_date=unsub_date_23, args=[
                      Basic_var.unsub_list_23], misfire_grace_time=5)
    # 在unsub_time_01 01:00:15开始time_unsub
    scheduler.add_job(time_unsub, 'date', run_date=unsub_date_01, args=[
                      Basic_var.unsub_list_01], misfire_grace_time=5)
    scheduler.start()


def func_get_today_instrID(exchange_url: 'str', date: 'datetime.date'):
    '''
    根据date和url合成链接，在shfe官网获得有效合约
    修改各合约格式为exchange.instrid
    返回修改后列表
    如异常则返回0.'''
    try:
        url = exchange_url + date.strftime(r"%Y%m%d") + '.dat'
        r = requests.get(url)
        df = pd.DataFrame(json.loads(r.content)['ContractDailyTradeArgument'])
        instr_list = list(df.INSTRUMENTID.values)
        instr_list = [('SHFE.' + x) for x in instr_list]
        print(len(instr_list), 'len(all_instrID_list)')
        if len(instr_list) != 0:
            return instr_list
        else:
            return 0
    except:
        return 0


def func_notify():
    pass


def init_prepare(exchange_url: 'str'):
    '''
    0、判断是否为交易日
    1、获取交易所instr
    2、修改trading_day 非交易日 则设置Binfo.Trading_day为False返回-1
    3、创建接收数据daily_channel_Que 放入main_start_Que
    4、创建控制行情按时间过滤的flag和取消订阅的schedule
    '''
    date = datetime.date.today()
    if date in list_date:
        for i in range(3):
            result = func_get_today_instrID(exchange_url, date)
            if result != 0:
                Basic_var.Trading_day = date.strftime(r"%Y%m%d")
                Basic_var.receive_data_Que = Queue()
                main_start_Que.put(Basic_var.receive_data_Que)
                Basic_var.excg_instrID_list = result
                create_timeflag_unsub_sche()
                return 1
            else:
                time.sleep(5)
        func_notify()
        return 0
    else:
        Basic_var.Trading_day = False
        return -1


list_date = [datetime.date(2022, 12, 29),
             datetime.date(2022, 12, 30),
             datetime.date(2023, 1, 3),
             datetime.date(2023, 1, 4),
             datetime.date(2023, 1, 5),
             datetime.date(2023, 1, 6),
             datetime.date(2023, 1, 9),
             datetime.date(2023, 1, 10),
             datetime.date(2023, 1, 11),
             datetime.date(2023, 1, 12),
             datetime.date(2023, 1, 13),
             datetime.date(2023, 1, 16),
             datetime.date(2023, 1, 17),
             datetime.date(2023, 1, 18),
             datetime.date(2023, 1, 19),
             datetime.date(2023, 1, 20),
             datetime.date(2023, 1, 30),
             datetime.date(2023, 1, 31),
             datetime.date(2023, 2, 1),
             datetime.date(2023, 2, 2),
             datetime.date(2023, 2, 3),
             datetime.date(2023, 2, 6),
             datetime.date(2023, 2, 7),
             datetime.date(2023, 2, 8),
             datetime.date(2023, 2, 9),
             datetime.date(2023, 2, 10),
             datetime.date(2023, 2, 13),
             datetime.date(2023, 2, 14),
             datetime.date(2023, 2, 15),
             datetime.date(2023, 2, 16),
             datetime.date(2023, 2, 17),
             datetime.date(2023, 2, 20),
             datetime.date(2023, 2, 21),
             datetime.date(2023, 2, 22),
             datetime.date(2023, 2, 23),
             datetime.date(2023, 2, 24),
             datetime.date(2023, 2, 27),
             datetime.date(2023, 2, 28),
             datetime.date(2023, 3, 1),
             datetime.date(2023, 3, 2),
             datetime.date(2023, 3, 3),
             datetime.date(2023, 3, 6),
             datetime.date(2023, 3, 7),
             datetime.date(2023, 3, 8),
             datetime.date(2023, 3, 9),
             datetime.date(2023, 3, 10),
             datetime.date(2023, 3, 13),
             datetime.date(2023, 3, 14),
             datetime.date(2023, 3, 15),
             datetime.date(2023, 3, 16),
             datetime.date(2023, 3, 17),
             datetime.date(2023, 3, 20),
             datetime.date(2023, 3, 21),
             datetime.date(2023, 3, 22),
             datetime.date(2023, 3, 23),
             datetime.date(2023, 3, 24),
             datetime.date(2023, 3, 27),
             datetime.date(2023, 3, 28),
             datetime.date(2023, 3, 29),
             datetime.date(2023, 3, 30),
             datetime.date(2023, 3, 31),
             datetime.date(2023, 4, 3),
             datetime.date(2023, 4, 4),
             datetime.date(2023, 4, 6),
             datetime.date(2023, 4, 7),
             datetime.date(2023, 4, 10),
             datetime.date(2023, 4, 11),
             datetime.date(2023, 4, 12),
             datetime.date(2023, 4, 13),
             datetime.date(2023, 4, 14),
             datetime.date(2023, 4, 17),
             datetime.date(2023, 4, 18),
             datetime.date(2023, 4, 19),
             datetime.date(2023, 4, 20),
             datetime.date(2023, 4, 21),
             datetime.date(2023, 4, 24),
             datetime.date(2023, 4, 25),
             datetime.date(2023, 4, 26),
             datetime.date(2023, 4, 27),
             datetime.date(2023, 4, 28),
             datetime.date(2023, 5, 2),
             datetime.date(2023, 5, 3),
             datetime.date(2023, 5, 4),
             datetime.date(2023, 5, 5),
             datetime.date(2023, 5, 8),
             datetime.date(2023, 5, 9),
             datetime.date(2023, 5, 10),
             datetime.date(2023, 5, 11),
             datetime.date(2023, 5, 12),
             datetime.date(2023, 5, 15),
             datetime.date(2023, 5, 16),
             datetime.date(2023, 5, 17),
             datetime.date(2023, 5, 18),
             datetime.date(2023, 5, 19),
             datetime.date(2023, 5, 22),
             datetime.date(2023, 5, 23),
             datetime.date(2023, 5, 24),
             datetime.date(2023, 5, 25),
             datetime.date(2023, 5, 26),
             datetime.date(2023, 5, 29),
             datetime.date(2023, 5, 30),
             datetime.date(2023, 5, 31),
             datetime.date(2023, 6, 1),
             datetime.date(2023, 6, 2),
             datetime.date(2023, 6, 5),
             datetime.date(2023, 6, 6),
             datetime.date(2023, 6, 7),
             datetime.date(2023, 6, 8),
             datetime.date(2023, 6, 9),
             datetime.date(2023, 6, 12),
             datetime.date(2023, 6, 13),
             datetime.date(2023, 6, 14),
             datetime.date(2023, 6, 15),
             datetime.date(2023, 6, 16),
             datetime.date(2023, 6, 19),
             datetime.date(2023, 6, 20),
             datetime.date(2023, 6, 21),
             datetime.date(2023, 6, 23),
             datetime.date(2023, 6, 26),
             datetime.date(2023, 6, 27),
             datetime.date(2023, 6, 28),
             datetime.date(2023, 6, 29),
             datetime.date(2023, 6, 30),
             datetime.date(2023, 7, 3),
             datetime.date(2023, 7, 4),
             datetime.date(2023, 7, 5),
             datetime.date(2023, 7, 6),
             datetime.date(2023, 7, 7),
             datetime.date(2023, 7, 10),
             datetime.date(2023, 7, 11),
             datetime.date(2023, 7, 12),
             datetime.date(2023, 7, 13),
             datetime.date(2023, 7, 14),
             datetime.date(2023, 7, 17),
             datetime.date(2023, 7, 18),
             datetime.date(2023, 7, 19),
             datetime.date(2023, 7, 20),
             datetime.date(2023, 7, 21),
             datetime.date(2023, 7, 24),
             datetime.date(2023, 7, 25),
             datetime.date(2023, 7, 26),
             datetime.date(2023, 7, 27),
             datetime.date(2023, 7, 28),
             datetime.date(2023, 7, 31),
             datetime.date(2023, 8, 1),
             datetime.date(2023, 8, 2),
             datetime.date(2023, 8, 3),
             datetime.date(2023, 8, 4),
             datetime.date(2023, 8, 7),
             datetime.date(2023, 8, 8),
             datetime.date(2023, 8, 9),
             datetime.date(2023, 8, 10),
             datetime.date(2023, 8, 11),
             datetime.date(2023, 8, 14),
             datetime.date(2023, 8, 15),
             datetime.date(2023, 8, 16),
             datetime.date(2023, 8, 17),
             datetime.date(2023, 8, 18),
             datetime.date(2023, 8, 21),
             datetime.date(2023, 8, 22),
             datetime.date(2023, 8, 23),
             datetime.date(2023, 8, 24),
             datetime.date(2023, 8, 25),
             datetime.date(2023, 8, 28),
             datetime.date(2023, 8, 29),
             datetime.date(2023, 8, 30),
             datetime.date(2023, 8, 31),
             datetime.date(2023, 9, 1),
             datetime.date(2023, 9, 4),
             datetime.date(2023, 9, 5),
             datetime.date(2023, 9, 6),
             datetime.date(2023, 9, 7),
             datetime.date(2023, 9, 8),
             datetime.date(2023, 9, 11),
             datetime.date(2023, 9, 12),
             datetime.date(2023, 9, 13),
             datetime.date(2023, 9, 14),
             datetime.date(2023, 9, 15),
             datetime.date(2023, 9, 18),
             datetime.date(2023, 9, 19),
             datetime.date(2023, 9, 20),
             datetime.date(2023, 9, 21),
             datetime.date(2023, 9, 22),
             datetime.date(2023, 9, 25),
             datetime.date(2023, 9, 26),
             datetime.date(2023, 9, 27),
             datetime.date(2023, 9, 28),
             datetime.date(2023, 10, 6),
             datetime.date(2023, 10, 9),
             datetime.date(2023, 10, 10),
             datetime.date(2023, 10, 11),
             datetime.date(2023, 10, 12),
             datetime.date(2023, 10, 13),
             datetime.date(2023, 10, 16),
             datetime.date(2023, 10, 17),
             datetime.date(2023, 10, 18),
             datetime.date(2023, 10, 19),
             datetime.date(2023, 10, 20),
             datetime.date(2023, 10, 23),
             datetime.date(2023, 10, 24),
             datetime.date(2023, 10, 25),
             datetime.date(2023, 10, 26),
             datetime.date(2023, 10, 27),
             datetime.date(2023, 10, 30),
             datetime.date(2023, 10, 31),
             datetime.date(2023, 11, 1),
             datetime.date(2023, 11, 2),
             datetime.date(2023, 11, 3),
             datetime.date(2023, 11, 6),
             datetime.date(2023, 11, 7),
             datetime.date(2023, 11, 8),
             datetime.date(2023, 11, 9),
             datetime.date(2023, 11, 10),
             datetime.date(2023, 11, 13),
             datetime.date(2023, 11, 14),
             datetime.date(2023, 11, 15),
             datetime.date(2023, 11, 16),
             datetime.date(2023, 11, 17),
             datetime.date(2023, 11, 20),
             datetime.date(2023, 11, 21),
             datetime.date(2023, 11, 22),
             datetime.date(2023, 11, 23),
             datetime.date(2023, 11, 24),
             datetime.date(2023, 11, 27),
             datetime.date(2023, 11, 28),
             datetime.date(2023, 11, 29),
             datetime.date(2023, 11, 30),
             datetime.date(2023, 12, 1),
             datetime.date(2023, 12, 4),
             datetime.date(2023, 12, 5),
             datetime.date(2023, 12, 6),
             datetime.date(2023, 12, 7),
             datetime.date(2023, 12, 8),
             datetime.date(2023, 12, 11),
             datetime.date(2023, 12, 12),
             datetime.date(2023, 12, 13),
             datetime.date(2023, 12, 14),
             datetime.date(2023, 12, 15),
             datetime.date(2023, 12, 18),
             datetime.date(2023, 12, 19),
             datetime.date(2023, 12, 20),
             datetime.date(2023, 12, 21),
             datetime.date(2023, 12, 22),
             datetime.date(2023, 12, 25),
             datetime.date(2023, 12, 26),
             datetime.date(2023, 12, 27),
             datetime.date(2023, 12, 28),
             datetime.date(2023, 12, 29)]
# import exchange_calendars as xcals
# xshg = xcals.get_calendar("XSHG")
# list_date = list(xshg.schedule.loc["2022-12-29":"2024-01-01"].open.dt.date.values)
